package yambal.net.google.Photo
{
	import com.adobe.utils.DateUtil;
	
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	
	import mx.collections.ArrayCollection;
	
	import yambal.net.google.Authentication;
	import yambal.net.google.Requester;
	import yambal.net.google.events.PicasaAlbumEvent;
	import yambal.net.google.events.PicasaEvent;
	import yambal.net.google.events.PicasaPhotoEvent;
	import yambal.net.google.events.RequesterEvent;
	
	[Event(name="album_list", type='yambal.net.google.events.PicasaEvent')]
	[Event(name="add_album", type='yambal.net.google.events.PicasaEvent')]
	[Event(name="update_photo", type='yambal.net.google.events.PicasaPhotoEvent')]
	[Event(name="add_photo", type='yambal.net.google.events.PicasaAlbumEvent')]
	[Event(name="list_photo", type='yambal.net.google.events.PicasaAlbumEvent')]
	public class Picasa extends Requester
	{
		
		public static const PICASA_EP:String = "http://picasaweb.google.com/data/feed/api/user/";
		
		public static const PICASA_ACCESS_PUBLIC:String = "public";
		public static const PICASA_ACCESS_PRIVATE:String = "private";
		public static const PICASA_ACCESS_PROTECTED:String = "protected";
		
		public var userID:String;
		public var userNicname:String;
		public var updated:Date;
		
		[Bindable]
		public var Albums:ArrayCollection;
		
		public var iconUrl:String;

		public function Picasa(){
		}
		
		public override function toString():String{
			return this.userID + "(" + this.userNicname + ")";
		}
		
		/**
		 * Authenticate
		 * 	もし、認証が必要な操作を行う場合は
		 *	setAuthenticateを行います。
		 **/
		public function setAuthenticate(email:String, password:String):void{
			var auth:Authentication = new Authentication();

			auth.addEventListener(Event.COMPLETE, this.onAuthenticate); 
			auth.authenticate(email, password, 'lh2');
		}
		
		private function onAuthenticate(e:Event):void{
			var auth:Authentication = e.currentTarget as Authentication;
			auth.removeEventListener(Event.COMPLETE, this.onAuthenticate);
			
			this.Auth = auth;
			this.setAlbumList();
		}

		/**
		 * getAlbumList
		 **/
		public function setAlbumList(userID:String = null):void{
			this.Albums = null;
			
			if(userID != null && userID != this.userID){
				// もし、対象のユーザが指定されているならば
				trace("target-user:" + PICASA_EP + userID);

			}else if(this.Auth != null && this.Auth.is_ok && this.Auth.service == 'lh2'){
				// もし、認証済ならばそのユーザを使う
				this.addEventListener(RequesterEvent.RESPONSE, this.onResponseGetAlbum);
				this.request(PICASA_EP + "default");
				
			}else{
				trace('false');
			}
		}
		
		private function onResponseGetAlbum(e:RequesterEvent):void{
			this.removeEventListener(RequesterEvent.RESPONSE,this.onResponseGetAlbum);
			
			var res:XML = e.result;
			
			var atom:Namespace = res.namespace();
			var openSearch:Namespace = res.namespace('openSearch');
			var gphoto:Namespace = res.namespace('gphoto');
			
			this.userID = res.atom::title;
			this.userNicname = res.atom::author;
			this.updated = DateUtil.parseW3CDTF(res.atom::updated);
			this.iconUrl = res.atom::icon;
			
			var albums:Array = new Array();
			for each (var entry:XML in res.atom::entry) {
				var album:PicasaAlbum = this.parseToAlbum(entry);
				albums.push(album);
			}
			this.Albums = new ArrayCollection(albums);
			
			this.dispatchEvent(new PicasaEvent(PicasaEvent.ALBUM_LIST, albums));
		}
		
		// -----------------------------------------------------------------------------------------
		/**
		 * アルバムを追加する
		 **/
		public function addAlbum(title:String, access:String = PICASA_ACCESS_PROTECTED, commentingEnabled:Boolean = true, keywords:Array = null, summary:String = "", location:String = ""):void{
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, this.onAddAlbum);
			
			var req:URLRequest = new URLRequest();
			req.url = "http://picasaweb.google.com/data/feed/api/user/" + this.userID;
			req.method = URLRequestMethod.POST;
			
			req.requestHeaders.push(new URLRequestHeader('Authorization', 'GoogleLogin auth=' + this.Auth.auth));
			req.requestHeaders.push(new URLRequestHeader('Content-Type','application/atom+xml'));
			req.data = this.getAddAlbumAtom(title, access, commentingEnabled, keywords, summary, location);
			loader.load(req);
		} 
		
		private function onAddAlbum(e:Event):void{
			var loader:URLLoader = e.currentTarget as URLLoader;
			loader.removeEventListener(Event.COMPLETE, this.onAddAlbum);
			
			var res:XML = new XML(loader.data);
			var addAlbum:PicasaAlbum = this.parseToAlbum(res);
			this.Albums.addItem(addAlbum);
			
			this.dispatchEvent(new PicasaEvent(PicasaEvent.ADD_ALBUM,[addAlbum]));
		}
		
		// -----------------------------------------------------------------------------------------
		/**
		 * Albumを削除する
		 **/
		public function deleteAlbum(album:PicasaAlbum):void{
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, this.onDeleteAlbum);
			
			var req:URLRequest = new URLRequest();
			req.url = album.edit_endpoint;
			req.method = URLRequestMethod.DELETE;
			
			req.requestHeaders.push(new URLRequestHeader('Authorization', 'GoogleLogin auth=' + this.Auth.auth));
			
			loader.load(req);
		}
		
		private function onDeleteAlbum(e:Event):void{
			var loader:URLLoader = e.currentTarget as URLLoader;
			loader.removeEventListener(Event.COMPLETE, this.onDeleteAlbum);
			
			this.setAlbumList();
		}
		
		// -----------------------------------------------------------------------------------------
		public function modifyAlbum(album:PicasaAlbum):void{
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, this.onModifyAlbum);
			
			var req:URLRequest = new URLRequest();
			req.url = album.edit_endpoint;
			
			req.requestHeaders.push(new URLRequestHeader('Authorization', 'GoogleLogin auth=' + this.Auth.auth));
			req.requestHeaders.push(new URLRequestHeader('Content-Type','application/atom+xml'));
			req.data = this.getAddAlbumAtom("アルバムのアップデート");
			
			req.method = URLRequestMethod.PUT;

			loader.load(req);
		}
		
		private function onModifyAlbum(e:Event):void{
			var loader:URLLoader = e.currentTarget as URLLoader;
			loader.removeEventListener(Event.COMPLETE, this.onModifyAlbum);
			
			this.setAlbumList();
		}
		
		// --------------------------------------------------------------------
		/**
		 * 配下AlbumのPHOTOがアップデートした時にAlbum自身から呼び出し
		 * イベントをListenしない工夫なんだけど、如何わしいな。
		 **/
		public function onUpdatePhoto(updated:PicasaPhoto):void{
			this.dispatchEvent(new PicasaPhotoEvent(PicasaPhotoEvent.UPDATE_PHOTO, updated));
		}
		
		public function onAddPhoto(album:PicasaAlbum, add_photo:PicasaPhoto, photo_list:Array):void{
			this.dispatchEvent(new PicasaAlbumEvent(PicasaAlbumEvent.ADD_PHOTO, album, add_photo, photo_list));
		}
		
		public function onListPhoto(album:PicasaAlbum, photo_list:Array):void{
			this.dispatchEvent(new PicasaAlbumEvent(PicasaAlbumEvent.LIST_PHOTO, album, null, photo_list));
		}
		
		// アルバムの追加に使用するXML（Atom）を返す
		private function getAddAlbumAtom(title:String, access:String = PICASA_ACCESS_PROTECTED, commentingEnabled:Boolean = true, keywords:Array = null, summary:String = "", location:String = ""):XML{
			var data:String = '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gphoto="http://schemas.google.com/photos/2007">' + 
					'<title type="text">' + title + '</title>' + 
					'<summary type="text">' + summary + '</summary>' + 
					'<gphoto:location>' + location + '</gphoto:location>' + 
					'<gphoto:access>' + access + '</gphoto:access>' + 
					'<gphoto:commentingEnabled>' + commentingEnabled.toString() + '</gphoto:commentingEnabled>' + 
					'<gphoto:timestamp>' + new Date().time + '</gphoto:timestamp>' + 
					'<media:group>';
			if(keywords != null){
				data += '<media:keywords>' + keywords.join(', ') + '</media:keywords>'
			}else{
				data += '<media:keywords/>';
			}
			data += '</media:group>' + 
					'<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/photos/2007#album"></category>' + 
					'</entry>';
			return new XML(data);
		}
		
		// -----------------------------------------------------------------------------------------
		/**
		 * EntryをAlbumにパースする
		 **/
		private function parseToAlbum(entry:XML):PicasaAlbum{
			var atom:Namespace = entry.namespace();
			var gphoto:Namespace = entry.namespace('gphoto');
			
			var album:PicasaAlbum = new PicasaAlbum();
				album.picasa = this;
				
				// parse entry
				album.id = entry.gphoto::id;
				album.published = DateUtil.parseW3CDTF(entry.atom::published);
				album.updated = DateUtil.parseW3CDTF(entry.atom::updated);
				album.title = entry.atom::title;
				album.summary = entry.atom::summary;
				album.name = entry.gphoto::name;
				album.access = entry.gphoto::access;
				album.timestamp = entry.gphoto::timestamp;
				album.numphotos = entry.gphoto::numphotos;
				album.numphotosremaining = entry.gphoto::numphotosremaining;
				album.bytesUsed = entry.gphoto::bytesUsed;
				album.user = entry.gphoto::user;
				album.nickname = entry.gphoto::nickname;
				album.commentingEnabled = entry.gphoto::commentingEnabled == "true";
				album.commentCount = entry.gphoto::commentCount;
				
				var links:XMLList = entry.atom::link;
				for each (var link:XML in entry.atom::link) {
					if(link.@rel == "edit"){
						album.edit_endpoint = link.@href;
					}
				}
			
			return album;
		}
	}
}